﻿using System.Collections.Generic;
using System.Linq;
using LibraryHub.Core.Models.User;
using LibraryHub.DataAccess.EntityFramework;

namespace LibraryHub.DataAccess
{
    public class UsersDa
    {
        private readonly LibraryHubContext db = DatabaseConnection.Db;

        public IEnumerable<UserModel> GetUsersList()
        {
            var users = (from b in db.Users
                         select b).ToList();
            var result = new List<UserModel>(users.Count);

            foreach (var u in users)
            {
                // Getting password is probably not good.
                var tmp = new UserModel
                              {
                                  Id = u.Id,
                                  Login = u.Login,
                                  FullName = u.FullName,
                                  Password = u.Password,
                                  Role = (UserRoleEnum)u.Role
                              };
                result.Add(tmp);
            }

            return result;
        }

        public bool AddUser(UserModel user)
        {
            var efUser = new EfUser
                             {
                                 Login = user.Login,
                                 Password = user.Password,
                                 FullName = user.FullName,
                                 Role = (int)user.Role
                             };
            db.Users.Add(efUser); //TODO: No validation at all at the moment. I don't know what is the proper way of enforcing validation.
            int changesCount = db.SaveChanges();

            if (changesCount > 0)
            {
                return true;
            }
            return false;
        }

        #region Find

        #region Single

        public UserModel FindUser(int id)
        {
            EfUser user = db.Users.Find(id); //TODO: no validation.
            // Getting password is probably not good.
            var result = new UserModel
                             {
                                 Id = user.Id,
                                 Login = user.Login,
                                 Password = user.Password,
                                 FullName = user.FullName,
                                 Role = (UserRoleEnum)user.Role
                             };
            // Long stuff like this a) fits in my monitor b) being automatically wrapped by ReSharper. Should I still format code to fit some fixed number of characters? It's different in every environment, but I believe it's not 80 characters anymore.
            return result;
        }

        public UserModel FindUserByLogin(string login)
        {
            var user = (from u in db.Users
                        where u.Login == login
                        select u).FirstOrDefault();
            if (user == null)
            {
                return null;
            }

            // Getting password is probably not good.
            var result = new UserModel
                             {
                                 Id = user.Id,
                                 Login = user.Login,
                                 Password = user.Password,
                                 FullName = user.FullName,
                                 Role = (UserRoleEnum)user.Role
                             };

            return result;
        }

        #endregion

        #region Multiple

        public IEnumerable<UserModel> FindUsersByLogin(string login)
        {
            var users = (from u in db.Users
                         where u.Login.Contains(login)
                         select u).ToList();

            var result = new List<UserModel>(users.Count);

            foreach (var u in users)
            {
                // Getting password is probably not good.
                var tmp = new UserModel
                              {
                                  Id = u.Id,
                                  Login = u.Login,
                                  FullName = u.FullName,
                                  Password = u.Password,
                                  Role = (UserRoleEnum)u.Role
                              };
                result.Add(tmp);
            }

            return result;
        }

        public IEnumerable<UserModel> FindUsersByFullName(string fullName)
        {
            var users = (from u in db.Users
                         where u.FullName.Contains(fullName)
                         select u).ToList();

            var result = new List<UserModel>(users.Count);

            foreach (var u in users)
            {
                // Getting password is probably not good.
                var tmp = new UserModel
                              {
                                  Id = u.Id,
                                  Login = u.Login,
                                  FullName = u.FullName,
                                  Password = u.Password,
                                  Role = (UserRoleEnum)u.Role
                              };
                result.Add(tmp);
            }

            return result;
        }

        public IEnumerable<UserModel> FindUsersByRole(UserRoleEnum role)
        {
            var users = (from u in db.Users
                         where u.Role == (int)role
                         select u).ToList();

            var result = new List<UserModel>(users.Count);

            foreach (var u in users)
            {
                // Getting password is probably not good.
                var tmp = new UserModel
                              {
                                  Id = u.Id,
                                  Login = u.Login,
                                  FullName = u.FullName,
                                  Password = u.Password,
                                  Role = (UserRoleEnum)u.Role
                              };
                result.Add(tmp);
            }

            return result;
        }

        #endregion

        #endregion

        public bool EditUser(UserModel user)
        {
            EfUser efUser = db.Users.Find(user.Id);
            if (efUser.Id == user.Id)
            {
                efUser.Login = user.Login;
                efUser.Password = user.Password;
                efUser.FullName = user.FullName;
                efUser.Role = (int)user.Role;
                //TODO: still no validation.
                int changesCount = db.SaveChanges();

                return true;
            }

            return false;
        }

        public bool DeleteUser(int id)
        {
            EfUser efUser = db.Users.Find(id);
            db.Users.Remove(efUser); //TODO: no validation.
            int changesCount = db.SaveChanges();

            if (changesCount > 0)
            {
                return true;
            }
            return false;
        }
    }
}
